import 'package:dio/dio.dart';
import 'package:universal_io/io.dart';

import '../common.dart';

export 'result.dart';
export 'server_result.dart';

typedef SuccessCallback = void Function(dynamic data);
typedef FailCallback = void Function(String msg);

enum ApiMethod {
  get,
  post,
}

enum ApiError {
  timeOut,
}

Dio initDio() {
  BaseOptions _baseOptions = BaseOptions(connectTimeout: const Duration(seconds: 15));
  Dio dio = Dio(_baseOptions);
  // (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate  = (client) {
  //   client.badCertificateCallback=(X509Certificate cert, String host, int port){
  //     // if(cert.pem==PEM){ // Verify the certificate
  //     //   return true;
  //     // }
  //     logd("Api", "cert:"+cert.pem);
  //     return true;
  //   };
  // };

  // dio.interceptors
  //     .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
  //   print('走网络请求了设置头部了');
  //   // options.queryParameters['Authorization'] =
  //   //     SpUtil.getString('token', defValue: '');
  //   return options;
  // }));
  return dio;
}

class Api {
  static const tag = "Api";
  static final Dio _dio = initDio();

  static Future<dynamic> upload(String path, String filepath, String filename,
      {Map<String, dynamic>? headers, Map<String, dynamic>? body}) async {
    FormData formData;
    MultipartFile multipartFile =
        await MultipartFile.fromFile(filepath, filename: filename);
    if (body != null) {
      formData = FormData.fromMap({
        ...body,
        'file': multipartFile,
      });
    } else {
      formData = FormData.fromMap({
        'file': multipartFile,
      });
    }

    return request(path,
        method: ApiMethod.post, body: formData, headers: headers);
  }

  static Future<Response<T>> get<T>(
      String path, {
        Object? data,
        Map<String, dynamic>? queryParameters,
        Options? options,
        CancelToken? cancelToken,
        ProgressCallback? onReceiveProgress,
      }) async{
    return _dio.get(path,data: data,queryParameters: queryParameters);
  }

  static Future<dynamic> request(
    path, {
    ApiMethod method = ApiMethod.get,
    Map<String, dynamic>? headers,
    Map<String, dynamic>? query,
    dynamic body,
  }) async {
    Response? result;
    try {
      if (method == ApiMethod.get) {
        result = await _dio.get(path,
            queryParameters: query, options: Options(headers: headers));
      } else if (method == ApiMethod.post) {
        result = await _dio.post(path,
            queryParameters: query,
            data: body,
            options: Options(headers: headers));
      }
      if (result!.statusCode == 200) {
        return result.data;
      } else {
        logw(tag, "状态错误:" + result.toString());
        return Future.error("状态错误:" + result.toString());
      }
    } on DioError catch (e) {
      logd(tag, "请求错误:" + path + "\n" + query.toString());
      loge(tag, e.toString() + "\n");
      Show.error("网络错误:" + path + ",${e.message}");
      return Future.error("网络错误:${e.message}");
    } catch (e) {
      logd(tag, "其他错误:" + path + "\n" + e.toString());
      return Future.error("其他错误:" + path + "\n" + e.toString());
      // 非具体类型
      //print('Something really unknown: $e');
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<Result> serverRequest(
    String path, {
    Map<String, dynamic>? data,
    dynamic body,
    bool post = false,
    bool logcat = false,
  }) async {
    Response? response;
    var startTime = DateTime.now().millisecondsSinceEpoch;
    try {
      if (post) {
        response = await _dio.post(path, data: data);
      } else {
        response = await _dio.get(path, queryParameters: data);
      }

      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      Result result = Result.fromJsonResponse(response);
      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }
      return result;
    } on DioError catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, ${e.message}");
      //Show.error("网络错误:" + path + "," + e.message);
      return Result.fromNetworkError(e.message??"");
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "其他错误: ${timeConsuming}ms, $path, $e");
      return Result.fromNetworkError(e.toString());
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<Result> serverUploadForBytes(String path,
      {required List<int> fileData,
      required String fileName,
      Map<String, dynamic>? data,
      bool logcat = false}) async {
    FormData formData;
    MultipartFile multipartFile =
        MultipartFile.fromBytes(fileData, filename: fileName);
    if (data != null) {
      formData = FormData.fromMap({
        ...data,
        'file': multipartFile,
      });
    } else {
      formData = FormData.fromMap({
        'file': multipartFile,
      });
    }

    Response? response;
    final startTime = DateTime.now().millisecondsSinceEpoch;
    try {
      response = await _dio.post(path, data: formData);

      final timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      Result result = Result.fromJsonResponse(response);
      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }
      return result;
    } on DioError catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, ${e.message}");
      //Show.error("网络错误:" + path + "," + e.message);
      return Result.fromNetworkError(e.message??"");
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "其他错误: ${timeConsuming}ms, $path, $e");
      return Result.fromNetworkError(e.toString());
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<File?> downloadFile(String path,
      {required String savePath,
        bool logcat = false}) async {


    Response? response;
    final startTime = DateTime.now().millisecondsSinceEpoch;
    try {
      //response = await _dio.post(path, data: formData);
      response = await _dio.download(path, savePath);

      final timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }


      return null;
    } on DioError catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, ${e.message}");
      //Show.error("网络错误:" + path + "," + e.message);
      return null;
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "其他错误: ${timeConsuming}ms, $path, $e");
      return null;
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }
}
